using System;
using System.Threading;
using System.ComponentModel;
using CloundUploader.Framework.Common;

namespace CloundUploader.Framework.Upload
{
   public  class AutoScheduler
    {
        private bool active;
       private System.Threading.Timer timer;
        private int maxjob;
       private bool autoShutUp;
       IAutoUploadsParameters parameters;
       public AutoScheduler(IAutoUploadsParameters parameters)
        {
            if (parameters == null)
            {
                throw new ArgumentNullException("parameters");
            }
            this.parameters = parameters;
            parameters.ParameterChanged += new PropertyChangedEventHandler(Default_PropertyChanged);
            
            UploaderManager.Instance.EndAddBatchUploads += new EventHandler(Instance_EndAddBatchUploads);
            UploaderManager.Instance.UploadAdded += new EventHandler<UploaderEventArgs>(Instance_UploadAdded);
            UploaderManager.Instance.UploadEnded += new EventHandler<UploaderEventArgs>(Instance_UploadEnded);
            TimerCallback refreshCallBack = new TimerCallback(PersistList);
            TimeSpan refreshInterval = TimeSpan.FromMinutes(1);
            timer = new Timer(refreshCallBack, null, new TimeSpan(-1), refreshInterval);
            this.MaxJob = parameters.MaxJob;
            this.autoShutUp = parameters.AutoShutUp;
            if (parameters.AutoStart)
            {
                
                this.Active = true;
            }

        
        }
       void Default_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
       {
           if (e.PropertyName == "MaxJob")
           {
               this.maxjob = parameters.MaxJob;
           }
       }

        private int GetActiveJobsCount()
        {
            int count = 0;

            for (int i = 0; i < UploaderManager.Instance.Uploads.Count; i++)
            {
                if (UploaderManager.Instance.Uploads[i].IsWorking() &&
                    UploaderManager.Instance.Uploads[i].State != UploaderState.WaitingForReconnect)
                {
                    count++;
                }
            }

            return count;
        }
        public void Dispose()
        {
           // RestoreIfNecessary();

            if (timer != null)
            {
                timer.Dispose();
                timer = null;
            }
        }
        public bool Active
        {
            get { return active; }
            set
            {
                active = value;
                if (active)
                {
                    StartJobsIfNeeded();
                }
              
            }
        }
       public int MaxJob
       {
           get { return maxjob; }
           set
           {
               maxjob= value;
              
           }
       }
        private void PersistList(object state)
        {
            StartJobsIfNeeded();
        }
        void Instance_UploadRemoved(object sender, UploaderEventArgs e)
        {
            StartJobsIfNeeded();
        }

        void Instance_UploadEnded(object sender, UploaderEventArgs e)
        {
            StartJobsIfNeeded();
        }

        void Instance_EndAddBatchUploads(object sender, EventArgs e)
        {
            StartJobsIfNeeded();
        }

        void Instance_UploadAdded(object sender, UploaderEventArgs e)
        {
            if (!e.WillStart)
            {
                StartJobsIfNeeded();

                e.Uploader.StateChanged += delegate(object s, EventArgs ea)
                {
                    if (((Uploader)s).State == UploaderState.WaitingForReconnect)
                    {
                        StartJobsIfNeeded();
                    }
                };
            }
        }
        private void StartJobsIfNeeded()
        {
            if (!Active || UploaderManager.Instance.AddBatchCount > 0)
            {
               
                return;
            }

         

            int maxJobs = maxjob;

            using (UploaderManager.Instance.LockUploadList(false))
            {
                int count = GetActiveJobsCount();

                if (count < maxJobs)
                {
                    for (int i = 0;
                        (count < maxJobs) && i < UploaderManager.Instance.Uploads.Count;
                        i++)
                    {
                        Uploader d = UploaderManager.Instance.Uploads[i];
                        if (d.State != UploaderState.Ended && !d.IsWorking() && d.State != UploaderState.EndedWithError)
                        {
                            UploaderManager.Instance.Uploads[i].Start();
                            count++;
                        }
                    }
                }
                count = GetActiveJobsCount();
                if (autoShutUp == true && count==0)
                {
                    Shudown.PowerOff();
                }
            }

        }



    }
}
